/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.alibaba.dubbo.config.spring.schema;

import com.alibaba.dubbo.common.Version;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ConsumerConfig;
import com.alibaba.dubbo.config.ModuleConfig;
import com.alibaba.dubbo.config.MonitorConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.ProviderConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.spring.ReferenceBean;
import com.alibaba.dubbo.config.spring.ServiceBean;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;

/**
 * DubboNamespaceHandler
 * 
 * <pre>
 * Schema 处理器
 *
 * Dubbo基于Spring的Schema扩展进行加载
 *
 * 解析Schema
 * DubboNamespaceHandler会根据schema和节点名找到某个DubboBeanDefinitionParser，然后由DubboBeanDefinitionParser完成具体的解析工作。
 * 因此需要分别继承NamespaceHandlerSupport和实现BeanDefinitionParser类。
 *
 * 定制spring.handlers和spring.schemas
 * 需要做一些配置工作来告诉Spring我们准备使用自定义的标签元素，告诉Spring如何解析元素，否则Spring没那么聪明。
 * 这里需要2个配置文件，spring.handlers和spring.schemas(位于META-INF下即可)，用于告诉Spring自定义标签的文档结构以及解析它的类。
 *
 * (dubbo-config\dubbo-config-spring\src\main\resources\META-INF\dubbo.xsd)
 *  ==> spring.handlers：解析所使用的类(dubbo-config\dubbo-config-spring\src\main\resources\META-INF\spring.handlers)
 *  ==> spring.schemas：自定义标签的路径(dubbo-config\dubbo-config-spring\src\main\resources\META-INF\spring.schemas)
 *  ==> DubboNamespaceHandler：处理器
 *  ==> DubboBeanDefinitionParser：解析器
 *  ==> XxxxConfig：Schema的JavaBean建模
 *  	AbstractConfig：
 *  		AbstractMethodConfig：
 *  			AbstractInterfaceConfig：
 *  				AbstractReferenceConfig：
 *  					ConsumerConfig：服务消费者缺省值配置(http://dubbo.apache.org/zh-cn/docs/user/references/xml/dubbo-consumer.html)
 *  					ReferenceConfig：服务消费者引用服务配置(http://dubbo.apache.org/zh-cn/docs/user/references/xml/dubbo-reference.html)
 *  				AbstractServiceConfig：
 *  					ProviderConfig：服务提供者缺省值配置(http://dubbo.apache.org/zh-cn/docs/user/references/xml/dubbo-provider.html)
 *  					ServiceConfig：服务提供者暴露服务配置(http://dubbo.apache.org/zh-cn/docs/user/references/xml/dubbo-service.html)
 *  			MethodConfig：方法级配置(http://dubbo.apache.org/zh-cn/docs/user/references/xml/dubbo-method.html)
 *          ApplicationConfig：应用信息配置(http://dubbo.apache.org/zh-cn/docs/user/references/xml/dubbo-application.html)
 *          ModuleConfig：模块信息配置(http://dubbo.apache.org/zh-cn/docs/user/references/xml/dubbo-module.html)
 *          MonitorConfig：监控中心配置(http://dubbo.apache.org/zh-cn/docs/user/references/xml/dubbo-monitor.html)
 *          ProtocolConfig：服务提供者协议配置(http://dubbo.apache.org/zh-cn/docs/user/references/xml/dubbo-protocol.html)
 *          RegistryConfig：注册中心配置(http://dubbo.apache.org/zh-cn/docs/user/references/xml/dubbo-registry.html)
 *      ArgumentConfig：方法参数配置(http://dubbo.apache.org/zh-cn/docs/user/references/xml/dubbo-argument.html) 
 * </pre>
 *
 * @export
 */
public class DubboNamespaceHandler extends NamespaceHandlerSupport {

    static {
        Version.checkDuplicate(DubboNamespaceHandler.class);
    }

    @Override
    public void init() {
        registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
        registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
        registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
        registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
        registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
        registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
        registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
        registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
        registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
        registerBeanDefinitionParser("annotation", new AnnotationBeanDefinitionParser());
    }

}
